package demo7

// API 为facade 模块的外观接口，大部分代码使用此接口简化对facade类的访问。
// facade模块同时暴露了a和b 两个Module 的NewXXX和interface，其它代码如果需要使用细节功能时可以直接调用。
import "fmt"
// --------------------------------场景1-----------------------------------
// 设计分析：对外暴露用户调用的方法，内部的实现不对外暴露
// 官方案例，REST API 的实现内部实现了两个API NewAModuleAPI NewBModuleAPI 这两个
// 用户只需要调用外部的暴露的API 就可以实现里面的功能，并不需要了解实现的复杂原理
// 官方案例，REST API 的实现内部实现了两个API NewAModuleAPI NewBModuleAPI 这两个
// 分析 需要一个API  和NewAModuleAPI /NewBModuleAPI 接口，然后实现不同的方法

type API interface{
	// API 的内置实现方法，该方法的实现就是内部复杂逻辑的实现
	Test()
}

func NewModuleAPI() API{
	return &ModuleAPI{
		// 这里用到了构造方法
		a:NewAModuleAPI(),
		b:NewBModuleAPI(),
	}
}
// 这里使用的结构体里面嵌套的是接口，这样做的好处就是可以拓展
// 接口是抽象的，那么对应的实例就可以是多种多样，如果里面的属性是某个实例的话，那么耦合性就变强了
type ModuleAPI struct{
	a AModuleAPI
	b BMoudelAPI
}
// 这里就是外部调用实现的时候。内部复杂逻辑的实现
func (m *ModuleAPI)Test(){
	m.a.TestA()
	m.b.TestB()
}

// 对应内部内置实现的逻辑
type AModuleAPI interface{
	TestA()
}
type Api_A struct{}
func NewAModuleAPI() *Api_A{
	return &Api_A{}
}
func (*Api_A)TestA(){
	fmt.Println("------testA-------")
}

type BMoudelAPI interface{
	TestB()
}
type Api_B struct{}
func NewBModuleAPI() *Api_B{
	return &Api_B{}
}
func(*Api_B)TestB(){
	fmt.Println("------testB-------")
}
// 上面来源官方的案例，
// 分析该模式的结构， 该模式有结构体 和 接口来实现的，接口来定义业务逻辑的服务，结构体来定义内部业务实现的流程
// 简单来说接口的定义就是外部暴露实现的方法。外部用来调用即可
// 结构体定义的就是内部要实现的复杂业务逻辑的所有流程，外部不用去考虑实现过程，由于实现的过程，会用到一些方法
// 那么如果方法的实例是固定的话，那么就打破解耦的设计了，所以内部方法的实现用到了抽象的接口来定义，
// 那么整体格式如下

// 定义对外暴露方法的规则
type XX interface{
	method() // 方法
}
type XXSTR struct{
	attr_a OtherInterface_A // 接口
	attr_b OtherInterface_B // 接口
	// ... 
}
// 对应接口的复杂实现
type OtherInterface_A interface{
	method_a()
}
type OtherInterface_B interface{
	method_b()
}
// 以上就是该设计模式的整体思想
// --------------------------------场景2-----------------------------------

// 需求: 汽车跑
// DDD分析： 汽车--->car 跑----> run 
// 领域事件: 汽车-->打火--->松离合器--->踩油门--->跑
// 领域模型： car  openfire release  oil  run
// 领域服务设计: 用户不需要汽车中间发生了什么，但是用户仅仅调用RUN 汽车就在跑了
// 那么开始构造

type Enginer interface{
	Run()
}
// 某一辆车 
type Car struct{
	strike StrikeFire // 打火的接口设计， 这里一定要是接口，毕竟打火的方式有很多,方便拓展
	clutch ReleaseClutch // 同上不同的车离合器也是不同的
	throttle Throttle // 同上油门亦是如此
}
// 这里的构造方法，也是可以做出调整的，
// 所谓的构造就是根据不同的场景来构造场景需求的方法
func NewCar() *Car{
	return &Car{
		strike:NewOneFire(),
		clutch:NewOneClutch(),
		throttle:NewOneThrottle(),
	}
}
// 这里的实现有点类似 建造者设计模式，
// 不同的是，建造者设计模式，是某一个实例上然后实现接口的所有分层的方法实现
// 这里的原型设计模式，是不同的实例然后实现所有业务逻辑，有点分离的思想，不是分层的思想,
// 在一个最终的对外调用的实例中，完成所有复杂逻辑聚合的实现
func (c *Car)Run(){
	// 复杂逻辑实现
	c.strike.fire()
	c.clutch.release()
	c.throttle.stamp()
}

// 抽象定义
type StrikeFire interface{
	fire()
}
// 定义一个实现的实例 / 当然上面也说了 毕竟打火方式有很多，车的类型有很多，方便拓展这里使用一个实例，下面也是一样
// 自己想拓展可以自己进行拓展
type OneFire struct{}
func NewOneFire() *OneFire{
	return &OneFire{}
}
func (*OneFire)fire(){ fmt.Println("one Car is fire") } // 某一辆车在打火

// 抽象定义
type ReleaseClutch interface{
	release()
}
type OneClutch struct{}
func NewOneClutch() *OneClutch{
	return &OneClutch{}
}
func (*OneClutch)release(){ fmt.Println("one car is Clutch") } // one

// 抽象定义
type Throttle interface{
	stamp()
}
type OneThrottle struct{}
func NewOneThrottle() *OneThrottle{
	return &OneThrottle{}
}
func (*OneThrottle) stamp(){ fmt.Println("one car is stamp") } // one
// 总结上面，原型设计模式避免用户对源码的修改来运用的， | 原型用于复杂业务逻辑分离 ， 比如案例如上面，都是车的相关功能，分离成不同的实例
// 而建造者设计模式，用户可以根据抽象的接口定制不同的实例实现 | 建造者用于复杂业务逻辑分层， 比如用户登录，都是登录的功能，登录的实现复杂逻辑
// 分层成不同的实现方法，
// 从两者的作用面上来看，建造者的作用面小于原型设计的作用面，建造者是一个实例的拆分不同的方法，原型是多个实例来完成一个功能的实现
// 所以在原型设计里面还可以拆分成建造者

// --------------------------------场景3-----------------------------------
// 需求：第三方认证，
// 需求分析： 由于第三方存在着多变不定性，同时第三方相关的配置一旦逻辑写好之后，尽量的避免修改，此时可以使用该模式，
// 场景： 用户登录借助第三方来认证，比如蓝鲸的JWT或者一些运维平台的认证发布等等
// Thrid 第三方 auth() 需要认证| 认证前需要用户的信息获取和验证 --》 userInfo  Get() | userCheck verification()

type thrid interface{
	auth()
}

// 假设这里是蓝鲸运维平台的验证
type bule struct{
	// 需要用户的信息
	info UserInfoInterface // 这里获取用户信息使用接口，避免以后的获取方式有很多
	// 当然本地验证也要通过
	check UserCheckinterface // 这里校验的方式也是有很多
}
func NewBule() thrid{
	return &bule{
		info:NewUserInfo(),
		check:NewUserCheck(),
	}
}
func (b *bule)auth(){
	b.info.Get()
	b.check.Verification()
}

type UserInfoInterface interface{
	Get()
}
type userInfo struct{}
func NewUserInfo() UserInfoInterface{
	return &userInfo{}
}
func (*userInfo)Get() {fmt.Println("get user info")}
type UserCheckinterface interface{
	Verification()
}
type userCheck struct{}
func NewUserCheck() UserCheckinterface {
	return &userCheck{}
}
func (*userCheck)Verification() { fmt.Println("verification user info") }

// --------------------------------场景4-----------------------------------
// 结构型设计模式: 这里关于运用还是需要大量的实践，以及很多设计模式都有异曲同工之妙，所以如果
// 强行的去运用的话，或者在场景中不知道如何选择的话，只能通过实践来练习，所以没有最好的方案，
// 只有相对适合的方案
